package com.yiwyn.unity;

import com.yiwyn.demo.utils.modify.anno.modify.ModifyEventField;
import com.yiwyn.demo.utils.modify.anno.modify.ModifyType;
import com.yiwyn.demo.utils.modify.entity.ModifyEntity;
import com.yiwyn.demo.utils.modify.handle.ModifyAnnoHandleRouter;
import com.yiwyn.unity.domain.BaseModifyTemp;
import lombok.SneakyThrows;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


public class ModifyTempComponent {


    private static final Map<Class<?>, BaseModifyTemp> modifyTempMap = new HashMap<>();

    public static <T> ModifyEntity record(Class<? extends BaseModifyTemp<T>> tempClazz, T oldObject, T newObject) throws InstantiationException, IllegalAccessException {

        // 获取领域信息
        ModifyType modifyTypeAnnotation = tempClazz.getAnnotation(ModifyType.class);
        if (modifyTypeAnnotation == null) {
            return null;
        }

        // 初始化变更对象记录实体
        ModifyEntity modifyEntity = new ModifyEntity();
        modifyEntity.setModifyType(modifyTypeAnnotation.value());
        ArrayList<ModifyEntity.ModifyItem> modifyItems = new ArrayList<>();
        modifyEntity.setModifyItems(modifyItems);

        // 获取定义记录字段
        Field[] declaredFields = tempClazz.getDeclaredFields();

        // 获取真实字段
        Field[] realObjField = oldObject.getClass().getDeclaredFields();

        // 优化性能 提前转map
        Map<String, Field> realFieldMap = Arrays.stream(realObjField).collect(Collectors.toMap(Field::getName, f -> f));

        for (Field field : declaredFields) {

            Annotation[] annotations = field.getAnnotations();

            for (Annotation annotation : annotations) {

                Class<? extends Annotation> annotationClazz = annotation.annotationType();
                if (!ModifyAnnoHandleRouter.containsRoute(annotationClazz)) {
                    continue;
                }

                // 尝试获取真实的Field
                Field realField = realFieldMap.get(field.getName());

                if (realField == null) {
                    continue;
                }

                realField.setAccessible(true);

                // 获取新老值并进行对比，若相同则跳过
                Object oldObj = realField.get(oldObject);
                Object newObj = realField.get(newObject);

                if (Objects.equals(oldObj, newObj)) {
                    continue;
                }

                ModifyEntity.ModifyItem item = new ModifyEntity.ModifyItem();

                item.setOldValue(oldObj);
                item.setNewValue(newObj);

                ModifyEventField modifyEventField = field.getAnnotation(ModifyEventField.class);

                BaseModifyTemp baseModifyTemp = modifyTempMap.computeIfAbsent(tempClazz, new Function<Class<?>, BaseModifyTemp<T>>() {
                    @SneakyThrows
                    @Override
                    public BaseModifyTemp<T> apply(Class<?> aClass) {
                        return tempClazz.getDeclaredConstructor().newInstance();
                    }
                });
                baseModifyTemp.trigger(modifyEventField.eventId(), item);

                // 添加对变更字段列表中
                modifyItems.add(item);
            }
        }
        return modifyEntity;
    }


}
